﻿using ChenShiBao.DomainCommons.Model;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ChenShiBao.Infrastructure.EFCore
{
    public static class MediatorExtensions
    {
        /// <summary>
        /// 把rootAssembly及直接或者间接引用的程序集（排除系统程序集）中的MediatR 相关类进行注册
        /// </summary>
        /// <param name="services"></param>
        /// <param name="rootAssembly"></param>
        /// <returns></returns>
        public static IServiceCollection AddMediatR(this IServiceCollection services, IEnumerable<Assembly> assemblies)
        {
            //try
            //{
            //    foreach (var assembly in assemblies)
            //    {
            //        try
            //        {
            //            //var types = assembly.GetTypes()
            //            //    .Where(t => t.IsClass && !t.IsAbstract && typeof(IRequestHandler<>).IsAssignableFrom(t));
            //            //foreach (var type in types)
            //            //{
            //            //    //logger.LogInformation($"Registering type: {type.FullName}");
            //            //}

            //            var loadedAssembly = Assembly.Load(assembly.FullName);
            //            var types = loadedAssembly.GetExportedTypes()
            //                .Where(t => t.IsClass && !t.IsAbstract && typeof(IRequestHandler<>).IsAssignableFrom(t));
            //            foreach (var type in types)
            //            {
            //                //logger.LogInformation($"Registering type: {type.FullName}");
            //            }

            //        }
            //        catch (Exception ex)
            //        {
            //            //logger.LogError(ex, $"Failed to register types from assembly: {assembly.FullName}");
            //        }
            //    }

            //    services.AddMediatR(assemblies.ToArray());
            //}
            //catch (Exception ex)
            //{
            //    //logger.LogError(ex, "Failed to configure MediatR");
            //    throw;
            //}


            //return services.AddMediatR(assemblies.ToArray());

            var registeredTypes = new HashSet<Type>();
            foreach (var assembly in assemblies)
            {
                try
                {
                    var types = assembly.GetExportedTypes()
                        .Where(t => t.IsClass && !t.IsAbstract && typeof(IRequestHandler<>).IsAssignableFrom(t));
                    foreach (var type in types)
                    {
                        if (!registeredTypes.Contains(type))
                        {
                            services.AddMediatR((IEnumerable<Assembly>)type);
                            registeredTypes.Add(type);
                        }
                    }
                }
                catch (Exception ex)
                {
                    // 处理异常
                    Console.WriteLine($"Failed to register types from assembly: {assembly.FullName}, Error: {ex.Message}");
                }
            }

            return services;
        }
        public static async Task DispatchDomainEventsAsync(this IMediator mediator, DbContext ctx)
        {
            var domainEntities = ctx.ChangeTracker
                .Entries<IDomainEvents>()
                .Where(x => x.Entity.GetDomainEvents().Any());

            var domainEvents = domainEntities
                .SelectMany(x => x.Entity.GetDomainEvents())
                .ToList();//加ToList()是为立即加载，否则会延迟执行，到foreach的时候已经被ClearDomainEvents()了

            domainEntities.ToList()
                .ForEach(entity => entity.Entity.ClearDomainEvents());

            foreach (var domainEvent in domainEvents)
            {
                await mediator.Publish(domainEvent);
            }
        }
    }
}
